import numpy as np
# import math  # 已移除未使用的math
# from scipy import stats  # 已移除未使用的scipy.stats
import matplotlib.pyplot as plt
import pandas as pd
import os
import re

# GI transit time parameters
GI_TRANSIT_PARAMS = {
    # Gastric emptying time parameters
    'stomach': {
        'fasted': {
            'mean_h': 0.49,          # Mean (hours)
            'cv_percent': 35.1,      # Coefficient of variation (%)
            'distribution': 'lognormal'  # Distribution type
        },
        'fed': {
            'mean_h': 2.07,          # Mean (hours)
            'cv_percent': 18.5,      # Coefficient of variation (%)
            'distribution': 'lognormal'  # Distribution type
        }
    },
    
    # Small intestine transit time parameters
    'small_intestine': {
        'fasted': {
            'alpha': 2.92,           # Weibull shape parameter
            'beta': 4.04,            # Weibull scale parameter
            'distribution': 'weibull'  # Distribution type
        },
        'fed': {
            'mean_h': 3.6035,        # Mean (hours)
            'cv_percent': 39.93,     # Coefficient of variation (%)
            'distribution': 'lognormal'  # Distribution type
        }
    },
    
    # Colon transit time parameters
    'colon': {
        'fasted': {
            'mean_h': 24.0,          # Mean (hours)
            'cv_percent': 30.0,      # Coefficient of variation (%)
            'distribution': 'lognormal'  # Distribution type
        },
        'fed': {
            'mean_h': 24.0,          # Mean (hours)
            'cv_percent': 30.0,      # Coefficient of variation (%)
            'distribution': 'lognormal'  # Distribution type
        }
    }
}

# GI physiology parameters
GI_PHYSIOLOGY_PARAMS = {
    # Gastric physiology parameters
    'stomach': {
        'fasted': {
            'volume_ml': 50.0,       # Fasted stomach volume (mL)
            'ph': 1.7,               # Fasted stomach pH
            'buffer_capacity': 7.0   # Buffer capacity (mmol/L/pH)
        },
        'fed': {
            'volume_ml': 1000.0,     # Fed stomach volume (mL)
            'ph': 5.0,               # Fed stomach pH
            'buffer_capacity': 14.0  # Buffer capacity (mmol/L/pH)
        }
    },
    
    # Small intestine physiology parameters
    'small_intestine': {
        'duodenum': {
            'length_cm': 25.0,       # Length (cm)
            'radius_cm': 2.0,        # Radius (cm)
            'ph': 6.0,               # pH
            'transit_time_h': 0.3    # Transit time (hours)
        },
        'jejunum': {
            'length_cm': 118.0,      # Length (cm)
            'radius_cm': 1.6,        # Radius (cm)
            'ph': 6.5,               # pH
            'transit_time_h': 1.7    # Transit time (hours)
        },
        'ileum': {
            'length_cm': 157.0,      # Length (cm)
            'radius_cm': 1.5,        # Radius (cm)
            'ph': 7.4,               # pH
            'transit_time_h': 1.9    # Transit time (hours)
        }
    },
    
    # Colon physiology parameters
    'colon': {
        'length_cm': 150.0,          # Length (cm)
        'radius_cm': 2.5,            # Radius (cm)
        'ph': 6.5,                   # pH
        'water_absorption_percent': 90.0  # Water absorption percentage (%)
    }
}

# ========================
# GI MRT参数（Fluid and dissolved drug mean residence time）
# ========================
GI_MRT_PARAMS = {
    'stomach_lag_time': {
        'fasted': {'mean': 0, 'cv_percent': 0},
        'fed': {'mean': 0, 'cv_percent': 0}
    },
    'stomach_mrt': {
        'fasted': {'mean': 0.27, 'cv_percent': 36},
        'fed': {'mean': 1.18, 'cv_percent': 46.65}
    },
    'small_intestine_mrt': {
        'fasted': {'mean': 3.4, 'cv_percent': 9.19},
        'fed': {'mean': 4.73, 'cv_percent': 34.67}
    },
    'whole_colon_mrt': {
        'fasted': {'mean': 37.11, 'cv_percent': 47},
        'fed': {'mean': 52.87, 'cv_percent': 47}
    },
    'ascending_colon_mrt': {
        'fasted': {'mean': 18.91, 'cv_percent': 47},
        'fed': {'mean': 23.11, 'cv_percent': 47}
    }
}

# ========================
# Meal Event Fluid Volumes 参数
# ========================
MEAL_EVENT_FLUID_PARAMS = {
    'num_gastric_emptying_half_lives': 5,
    'total_fluid_volume_with_food_ml': {'mean': 531.07, 'cv_percent': 15, 'info': 'High Fat Fed'},
    'meal_consumption_time_h': {'mean': 0.335, 'cv_percent': 30},
    'zero_order_filling_rate_mlph': 1585.3,
    'max_stomach_volume_ml': 4000
}

# ========================
# Intestinal Anatomy Parameters
# ========================
INTESTINE_ANATOMY_PARAMS = {
    'total_length_m': {
        'SI': {'male_mean': 5.32, 'male_cv': 20.45, 'female_mean': 5.16, 'female_cv': 19.33},
        'Colon': {'male_mean': 1.26, 'male_cv': 12.25, 'female_mean': 1.33, 'female_cv': 11.81}
    },
    'si_fraction': {
        'Duodenum': 0.05,
        'Jejunum': 0.35,
        'Ileum': 0.6
    },
    'diameter_m': {
        'Duodenum': {'mean': 0.022, 'cv': 23.94},
        'Colon': {'mean': 0.04, 'cv': 24.58}
    },
    'regional_diameter_ratio': {
        'Jejunum/Duodenum': 0.94,
        'Ileum/Duodenum': 0.84
    },
    'enterocyte_height_um': {
        'SI': {'mean': 29.8, 'cv': 11, 'min': 20, 'max': 40},
        'Colon': {'mean': 29.8, 'cv': 11, 'min': 20, 'max': 40}
    },
    'enterocyte_volume_L': {
        'SI': 0.164429,
        'Colon': 0.017973
    },
    'length_diameter_option': 'New'  # 'Original' or 'New'
}

# ========================
# IMMC Cycle Time Parameters
# ========================
IMMC_CYCLE_PARAMS = {
    'cycle_time_h': {'mean': 1.55, 'cv_percent': 55}
}

# ========================
# Nested Enzyme Within Enterocyte (NEWE) Model Parameters
# ========================
NEWE_MODEL_PARAMS = {
    'enterocyte_lifespan_h': {'mean': 120, 'cv_percent': 30},
    'num_enterocyte_groups': 100
}

# ========================
# Enzyme and Protein Abundances Parameters
# ========================
ENZYME_PROTEIN_ABUNDANCE_PARAMS = [
    {'Parameter': 'SPPI (mg/small intestine)*', 'Mean': 5320, 'CV(%)': '-'},
    {'Parameter': 'User SPPI (mg/small intestine)*', 'Mean': 0, 'CV(%)': 30},
    {'Parameter': 'MPPI (mg/small intestine)', 'Mean': 2978, 'CV(%)': 30},
    {'Parameter': 'MPPC (mg/colon)*', 'Mean': 923, 'CV(%)': 30},
    {'Parameter': 'CPPI (mg/small intestine)', 'Mean': 2342, 'CV(%)': 31},
    {'Parameter': 'TMEPPI (mg/small intestine)*', 'Mean': 6399, 'CV(%)': 0},
    {'Parameter': 'TMEPPC (mg/colon)*', 'Mean': 184, 'CV(%)': 0}
]

# ========================
# CYP2C9 and CYP2B6 Genotype Data
# ========================
CYP_GENOTYPE_DATA = {
    'CYP2C9': [
        {'Genotype': '*1/*1', 'Frequency': 0.9344, 'Mean Abundance': 14.1, 'CV(%)': 72, 'Turnover Mean (1/h)': 0.03, 'Turnover CV(%)': 20},
        {'Genotype': '*1/*2', 'Frequency': 0.03, 'Mean Abundance': 13.7, 'CV(%)': 72, 'Turnover Mean (1/h)': 0.03, 'Turnover CV(%)': 20},
        {'Genotype': '*1/*3', 'Frequency': 0.03, 'Mean Abundance': 11.5, 'CV(%)': 72, 'Turnover Mean (1/h)': 0.03, 'Turnover CV(%)': 20},
        {'Genotype': '*2/*2', 'Frequency': 0, 'Mean Abundance': 9.7, 'CV(%)': 72, 'Turnover Mean (1/h)': 0.03, 'Turnover CV(%)': 20},
        {'Genotype': '*2/*3', 'Frequency': 0.000294, 'Mean Abundance': 7.1, 'CV(%)': 72, 'Turnover Mean (1/h)': 0.03, 'Turnover CV(%)': 20},
        {'Genotype': '*3/*3', 'Frequency': 0.00231, 'Mean Abundance': 4.6, 'CV(%)': 72, 'Turnover Mean (1/h)': 0.03, 'Turnover CV(%)': 20}
    ],
    'CYP2B6': [
        {'Genotype': '*1/*1', 'Frequency': 0.597, 'Mean Abundance': 0, 'CV(%)': 0, 'Turnover Mean (1/h)': 0, 'Turnover CV(%)': 0},
        {'Genotype': '*1/*2', 'Frequency': 0.137, 'Mean Abundance': 0, 'CV(%)': 0, 'Turnover Mean (1/h)': 0, 'Turnover CV(%)': 0},
        {'Genotype': '*1/*4', 'Frequency': 0.085, 'Mean Abundance': 0, 'CV(%)': 0, 'Turnover Mean (1/h)': 0, 'Turnover CV(%)': 0},
        {'Genotype': '*1/*5', 'Frequency': 0.002, 'Mean Abundance': 0, 'CV(%)': 0, 'Turnover Mean (1/h)': 0, 'Turnover CV(%)': 0},
        {'Genotype': '*1/*6', 'Frequency': 0.233, 'Mean Abundance': 0, 'CV(%)': 0, 'Turnover Mean (1/h)': 0, 'Turnover CV(%)': 0},
        {'Genotype': '*6/*6', 'Frequency': 0.046, 'Mean Abundance': 0, 'CV(%)': 0, 'Turnover Mean (1/h)': 0, 'Turnover CV(%)': 0}
    ]
}

# ========================
# GI CYP酶频率数据
# ========================
GI_CYP_FREQUENCIES = {
    'CYP2C9': {'EM': 0.934, 'PM': 0.003, 'IM1': 0.063, 'IM2': 0.0, 'UM': 0.0},
    'CYP2B6': {'EM': 0.524, 'PM': 0.068, 'IM1': 0.323, 'IM2': 0.0, 'UM': 0.085}
}

# ========================
# GI CYP酶丰度和周转数据
# ========================
GI_CYP_ABUNDANCES = {
    'CYP2C9': {
        'EM': {'mean': 14.1, 'cv': 72}, 'PM': {'mean': 13.7, 'cv': 72},
        'IM1': {'mean': 11.5, 'cv': 72}, 'IM2': {'mean': 9.7, 'cv': 72},
        'UM': {'mean': 4.6, 'cv': 72}, 'turnover_mean': 0.03, 'turnover_cv': 20
    },
    'CYP2B6': {
        'EM': {'mean': 0.0, 'cv': 0}, 'PM': {'mean': 0.0, 'cv': 0},
        'IM1': {'mean': 0.0, 'cv': 0}, 'IM2': {'mean': 0.0, 'cv': 0},
        'UM': {'mean': 0.0, 'cv': 0}, 'turnover_mean': 0.0, 'turnover_cv': 0
    }
}

# ========================
# GI转运体频率数据
# ========================
GI_TRANSPORTER_FREQUENCIES = {
    'ABCB1 (P-gp/MDR1)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'ABCC2 (MRP2)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'ABCG2 (BCRP)': {'ET': 0.44, 'PT': 0.1, 'IT': 0.46, 'UT': 0.0},
    'SLC15A1 (PepT1)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'SLC22A1 (OCT1)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'SLC22A4 (OCTN1)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'SLC22A5 (OCTN2)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'SLC22A6 (OAT1)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'SLC22A8 (OAT3)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0},
    'SLC47A1 (MATE1)': {'ET': 1.0, 'PT': 0.0, 'IT': 0.0, 'UT': 0.0}
}

# ========================
# GI转运体丰度和周转数据
# ========================
GI_TRANSPORTER_ABUNDANCES = {
    'ABCB1 (P-gp/MDR1)': {
        'ET': {'mean': 0.246, 'cv': 59}, 'PT': {'mean': 0.246, 'cv': 59},
        'IT': {'mean': 0.246, 'cv': 59}, 'UT': {'mean': 0.246, 'cv': 59},
        'turnover_mean': 0.054, 'turnover_cv': 28
    },
    'ABCC2 (MRP2)': {
        'ET': {'mean': 0.59, 'cv': 88}, 'PT': {'mean': 0.59, 'cv': 88},
        'IT': {'mean': 0.59, 'cv': 88}, 'UT': {'mean': 0.59, 'cv': 88},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'ABCG2 (BCRP)': {
        'ET': {'mean': 0.103, 'cv': 30}, 'PT': {'mean': 0.37, 'cv': 30},
        'IT': {'mean': 0.67, 'cv': 30}, 'UT': {'mean': 0.0, 'cv': 30},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'SLC15A1 (PepT1)': {
        'ET': {'mean': 0.5, 'cv': 50}, 'PT': {'mean': 0.5, 'cv': 50},
        'IT': {'mean': 0.5, 'cv': 50}, 'UT': {'mean': 0.5, 'cv': 50},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'SLC22A1 (OCT1)': {
        'ET': {'mean': 1.27, 'cv': 44}, 'PT': {'mean': 1.27, 'cv': 44},
        'IT': {'mean': 1.27, 'cv': 44}, 'UT': {'mean': 1.27, 'cv': 44},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'SLC22A4 (OCTN1)': {
        'ET': {'mean': 0.3, 'cv': 50}, 'PT': {'mean': 0.3, 'cv': 50},
        'IT': {'mean': 0.3, 'cv': 50}, 'UT': {'mean': 0.3, 'cv': 50},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'SLC22A5 (OCTN2)': {
        'ET': {'mean': 0.2, 'cv': 50}, 'PT': {'mean': 0.2, 'cv': 50},
        'IT': {'mean': 0.2, 'cv': 50}, 'UT': {'mean': 0.2, 'cv': 50},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'SLC22A6 (OAT1)': {
        'ET': {'mean': 0.8, 'cv': 50}, 'PT': {'mean': 0.8, 'cv': 50},
        'IT': {'mean': 0.8, 'cv': 50}, 'UT': {'mean': 0.8, 'cv': 50},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'SLC22A8 (OAT3)': {
        'ET': {'mean': 1.0, 'cv': 50}, 'PT': {'mean': 1.0, 'cv': 50},
        'IT': {'mean': 1.0, 'cv': 50}, 'UT': {'mean': 1.0, 'cv': 50},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    },
    'SLC47A1 (MATE1)': {
        'ET': {'mean': 0.146, 'cv': 51}, 'PT': {'mean': 0.146, 'cv': 51},
        'IT': {'mean': 0.146, 'cv': 51}, 'UT': {'mean': 0.146, 'cv': 51},
        'turnover_mean': 1.00E-06, 'turnover_cv': 30
    }
}

# ========================
# Distribution of Parameters Across Intestinal Segments
# ========================
DISTRIBUTION_ACROSS_INTESTINAL_SEGMENTS = {
    'Parameter': ['CYP 3A (Total %)', 'SPPI (Total %)', 'MPPI (Total %)', 'CPPI (Total %)', 'Blood Flow (Qint, %)', 'Transit Time (Total %)'],
    'Duodenum': [13.76, 14.88, 13.76, 14.88, 10.518, 5],
    'Jejunum I': [27.24, 26.9, 27.24, 26.9, 35.944, 17.5],
    'Jejunum II': [27.24, 26.9, 27.24, 26.9, 24.786, 17.5],
    'Ileum I': [7.94, 7.83, 7.94, 7.83, 7.3165, 15],
    'Ileum II': [7.94, 7.83, 7.94, 7.83, 7.3165, 15],
    'Ileum III': [7.94, 7.83, 7.94, 7.83, 7.1978, 15],
    'Ileum IV': [7.94, 7.83, 7.94, 7.83, 6.921, 15]
}

# ========================
# Physicochemical Parameters
# ========================
PHYSICOCHEMICAL_PARAMS = {
    'Ionic Product (Kw) (10⁻¹⁴ mol²/dm⁶)': 2.4,
    'Aqueous Diffusion Coefficients H⁺ (10⁻⁴ cm²/min)': 6.94,
    'Aqueous Diffusion Coefficients OH⁻ (10⁻⁴ cm²/min)': 7.2,
    'Water Concentration (mM)': 55560
}

# ========================
# GI Segment pH Parameters
# ========================
GI_PH_PARAMS = {
    'Segment': ['Stomach', 'Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV', 'Colon'],
    'pH Fasted': [1.5, 6.4, 6.5, 6.6, 6.8, 7, 7.1, 7.3, 6.6],
    'pH Fasted CV (%)': [38, 16, 13, 11, 10, 10, 7, 6, 13],
    'pH Fed': [5, 5.4, 6.5, 6.6, 6.8, 7, 7.1, 7.3, 6.33],
    'pH Fed CV (%)': [25, 11, 13, 11, 10, 10, 7, 6, 12]
}

# ========================
# Buffer Concentration, pKa, and Diffusion Coefficient Parameters
# ========================
GI_BUFFER_CONCENTRATION_PARAMS = {
    'Segment': ['Stomach', 'Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV', 'Colon'],
    'Fasted (mM)': [7.3, 6.53, 9.94, 9.94, 30, 30, 30, 30, 90.87],
    'CV Fasted (%)': [30, 30, 30, 30, 30, 30, 30, 30, 30],
    'Fed (mM)': [42.46, 34.19, 17.34, 17.34, 30, 30, 30, 30, 44.43],
    'CV Fed (%)': [30, 30, 30, 30, 30, 30, 30, 30, 30]
}

PKA_PARAMS = [
    {'Parameter': 'pKa 1', 'Value': 6.05, 'Notes': 'Acidic'},
    {'Parameter': 'pKa 2', 'Value': 9.79, 'Notes': 'Measured at 37 °C, ionic strength 0.15 M'},
    {'Parameter': 'pKa 1 (effective)', 'Value': 4.2, 'Notes': 'Effective acidic pKa'},
    {'Parameter': 'pKa 2 (repeat)', 'Value': 9.79, 'Notes': 'Same as above'}
]

DIFFUSION_COEFFICIENT_PARAMS = [
    {'Species': 'H₂CO₃', 'Diffusion Coefficient': 17.72},
    {'Species': 'HCO₃⁻', 'Diffusion Coefficient': 9.85},
    {'Species': 'CO₂', 'Diffusion Coefficient': 6.98}
]

# ========================
# GI Segment Velocity Parameters
# ========================
GI_VELOCITY_PARAMS = {
    'Segment': ['Stomach', 'Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV', 'Colon'],
    'Fasted (m/s)': [0.032, 0.005, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013],
    'CV Fasted (%)': [30, 30, 56, 56, 56, 56, 56, 56, 56],
    'Fed (m/s)': [0.032, 0.005, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013, 0.0013],
    'CV Fed (%)': [30, 30, 56, 56, 56, 56, 56, 56, 56]
}

# ========================
# GI Ion Concentration Parameters
# ========================
ION_CONCENTRATION_PARAMS = [
    # Chloride
    {'Ion': 'Chloride (Cl⁻)', 'Metric': 'Mean', 'Stomach': 102, 'Duodenum': 102.4, 'Jejunum I': 126, 'Jejunum II': 126, 'Ileum I': 113.3, 'Ileum II': 100.5, 'Ileum III': 84, 'Ileum IV': 67.4, 'Colon': 14, 'CV Stomach (%)': 27.5, 'CV Small Intestine (%)': 15.1, 'CV Colon (%)': 13},
    {'Ion': 'Chloride (Cl⁻)', 'Metric': 'Min', 'Stomach': 48, 'Duodenum': 64.6, 'Jejunum I': 92, 'Jejunum II': 92, 'Ileum I': 80.4, 'Ileum II': 71.4, 'Ileum III': 59.6, 'Ileum IV': 58, 'Colon': 7},
    {'Ion': 'Chloride (Cl⁻)', 'Metric': 'Max', 'Stomach': 173, 'Duodenum': 158.8, 'Jejunum I': 181, 'Jejunum II': 181, 'Ileum I': 157.5, 'Ileum II': 139.7, 'Ileum III': 116.7, 'Ileum IV': 79, 'Colon': 20},
    # Sodium
    {'Ion': 'Sodium (Na⁺)', 'Metric': 'Mean', 'Stomach': 68, 'Duodenum': 118.4, 'Jejunum I': 142, 'Jejunum II': 142, 'Ileum I': 136.3, 'Ileum II': 130.5, 'Ileum III': 128.9, 'Ileum IV': 127.2, 'Colon': 30, 'CV Stomach (%)': 42.6, 'CV Small Intestine (%)': 9.2, 'CV Colon (%)': 42},
    {'Ion': 'Sodium (Na⁺)', 'Metric': 'Min', 'Stomach': 19, 'Duodenum': 89.6, 'Jejunum I': 111, 'Jejunum II': 111, 'Ileum I': 107.4, 'Ileum II': 102.8, 'Ileum III': 101.5, 'Ileum IV': 112, 'Colon': 6},
    {'Ion': 'Sodium (Na⁺)', 'Metric': 'Max', 'Stomach': 122, 'Duodenum': 155.1, 'Jejunum I': 165, 'Jejunum II': 165, 'Ileum I': 171.8, 'Ileum II': 164.6, 'Ileum III': 162.5, 'Ileum IV': 138, 'Colon': 93},
    # Potassium
    {'Ion': 'Potassium (K⁺)', 'Metric': 'Mean', 'Stomach': 13.4, 'Duodenum': 11.2, 'Jejunum I': 5.4, 'Jejunum II': 5.4, 'Ileum I': 6.1, 'Ileum II': 6.7, 'Ileum III': 6.3, 'Ileum IV': 5.9, 'Colon': 77, 'CV Stomach (%)': 22.4, 'CV Small Intestine (%)': 38.9, 'CV Colon (%)': 11},
    {'Ion': 'Potassium (K⁺)', 'Metric': 'Min', 'Stomach': 8.4, 'Duodenum': 3.4, 'Jejunum I': 1.7, 'Jejunum II': 1.7, 'Ileum I': 4.6, 'Ileum II': 5, 'Ileum III': 4.7, 'Ileum IV': 5.3, 'Colon': 40},
    {'Ion': 'Potassium (K⁺)', 'Metric': 'Max', 'Stomach': 19.3, 'Duodenum': 32.1, 'Jejunum I': 11.6, 'Jejunum II': 11.6, 'Ileum I': 8, 'Ileum II': 8.8, 'Ileum III': 8.3, 'Ileum IV': 6.5, 'Colon': 108},
    # Calcium
    {'Ion': 'Calcium (Ca²⁺)', 'Metric': 'Mean', 'Stomach': 0.6, 'Duodenum': 0.5, 'Jejunum I': 0.5, 'Jejunum II': 0.5, 'Ileum I': 0.5, 'Ileum II': 0.5, 'Ileum III': 0.5, 'Ileum IV': 0.5, 'Colon': 20, 'CV Stomach (%)': 33.3, 'CV Small Intestine (%)': 60, 'CV Colon (%)': 34},
    {'Ion': 'Calcium (Ca²⁺)', 'Metric': 'Min', 'Stomach': 0.3, 'Duodenum': 0.1, 'Jejunum I': 0.1, 'Jejunum II': 0.1, 'Ileum I': 0.1, 'Ileum II': 0.1, 'Ileum III': 0.1, 'Ileum IV': 0.1, 'Colon': 7},
    {'Ion': 'Calcium (Ca²⁺)', 'Metric': 'Max', 'Stomach': 1.2, 'Duodenum': 1.3, 'Jejunum I': 1.3, 'Jejunum II': 1.3, 'Ileum I': 1.3, 'Ileum II': 1.3, 'Ileum III': 1.3, 'Ileum IV': 1.3, 'Colon': 85},
    # Generic Cation
    {'Ion': 'Generic Cation (x-)', 'Metric': 'Mean', 'Stomach': 1, 'Duodenum': 1, 'Jejunum I': 1, 'Jejunum II': 1, 'Ileum I': 1, 'Ileum II': 1, 'Ileum III': 1, 'Ileum IV': 1, 'Colon': 1, 'CV Stomach (%)': 0, 'CV Small Intestine (%)': 0, 'CV Colon (%)': 0},
    {'Ion': 'Generic Cation (x-)', 'Metric': 'Min', 'Stomach': 0.01, 'Duodenum': 0.01, 'Jejunum I': 0.01, 'Jejunum II': 0.01, 'Ileum I': 0.01, 'Ileum II': 0.01, 'Ileum III': 0.01, 'Ileum IV': 0.01, 'Colon': 0},
    {'Ion': 'Generic Cation (x-)', 'Metric': 'Max', 'Stomach': 1000, 'Duodenum': 1000, 'Jejunum I': 1000, 'Jejunum II': 1000, 'Ileum I': 1000, 'Ileum II': 1000, 'Ileum III': 1000, 'Ileum IV': 1000, 'Colon': 1000},
    # Generic Anion
    {'Ion': 'Generic Anion (X)', 'Metric': 'Mean', 'Stomach': 1, 'Duodenum': 1, 'Jejunum I': 1, 'Jejunum II': 1, 'Ileum I': 1, 'Ileum II': 1, 'Ileum III': 1, 'Ileum IV': 1, 'Colon': 1, 'CV Stomach (%)': 0, 'CV Small Intestine (%)': 0, 'CV Colon (%)': 0},
    {'Ion': 'Generic Anion (X)', 'Metric': 'Min', 'Stomach': 0.01, 'Duodenum': 0.01, 'Jejunum I': 0.01, 'Jejunum II': 0.01, 'Ileum I': 0.01, 'Ileum II': 0.01, 'Ileum III': 0.01, 'Ileum IV': 0.01, 'Colon': 0.01},
    {'Ion': 'Generic Anion (X)', 'Metric': 'Max', 'Stomach': 1000, 'Duodenum': 1000, 'Jejunum I': 1000, 'Jejunum II': 1000, 'Ileum I': 1000, 'Ileum II': 1000, 'Ileum III': 1000, 'Ileum IV': 1000, 'Colon': 1000}
]

# ========================
# GI Bile Salt Concentration Parameters
# ========================
GI_BILE_SALT_PARAMS = {
    'Segment': ['Stomach', 'Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV', 'Colon'],
    'CMC Fasted (mM)': [1, 1, 1, 1, 1, 1, 1, 1, 1],
    '[Bile] Fasted (mM)': [0.34, 3.31, 2.3, 3.55, 1.25, 1.25, 1.25, 1.25, 0.12],
    'CV [Bile] Fasted (%)': [134, 97, 100, 42, 30, 30, 30, 30, 104],
    'CMC Fed (mM)': [1, 1, 1, 1, 1, 1, 1, 1, 1],
    '[Bile] Fed (mM)': [0.34, 8.74, 10.03, 4.79, 5.86, 8.61, 8.06, 5.96, 0.59],
    'CV [Bile] Fed (%)': [216.7, 79, 73, 66, 84, 88, 65, 65, 70]
}

# ========================
# Villi, Plicae Circulares, Colon Crypts, Paracellular Parameters
# ========================
VILLI_PARAMS = {
    'Region': ['Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV'],
    'Channel Depth Mean (um)': [522.78, 448.81, 448.81, 289.94, 289.94, 289.94, 289.94],
    'Channel Depth CV(%)': [32.72, 21.82, 21.82, 49.37, 49.37, 49.37, 49.37],
    'Channel Width Mean (um)': [149.82, 121.69, 121.69, 129.81, 129.81, 129.81, 129.81],
    'Channel Width CV(%)': [27.68, 30.28, 30.28, 29.04, 29.04, 29.04, 29.04],
    'Density Mean (1/mm2)': [22.22, 22.22, 22.22, 22.22, 22.22, 22.22, 22.22],
    'Density CV(%)': [30, 30, 30, 30, 30, 30, 30],
    'Surface Area Expansion Factor': [6.05, 6.05, 6.05, 4.04, 4.04, 4.04, 4.04]
}

PLICAE_CIRCULARES_PARAMS = {
    'Region': ['Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV'],
    'Height Mean (mm)': [0.8, 0.8, 0.8, 0.8, 0.8, 0.8, 0.8],
    'Height CV(%)': [30, 30, 30, 30, 30, 30, 30],
    'Width Mean (mm)': [3, 3, 3, 3, 3, 3, 3],
    'Width CV(%)': [30, 30, 30, 30, 30, 30, 30],
    'Density Mean (1/cm)': [5, 5, 5, 5, 5, 5, 5],
    'Density CV(%)': [30, 30, 30, 30, 30, 30, 30],
    'Surface Area Expansion Factor': [3, 3, 3, 3, 3, 3, 3]
}

COLON_CRYPTS_PARAMS = {
    'Region': ['Colon'],
    'Depth Mean (um)': [400],
    'Depth CV(%)': [30],
    'Width Mean (um)': [50],
    'Width CV(%)': [30],
    'Density Mean (1/mm2)': [25],
    'Density CV(%)': [30],
    'Surface Area Expansion Factor': [2.5]
}

PARACELLULAR_PARAMS = {
    'Region': ['Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV', 'Colon'],
    'Pore Radius Mean (Å)': [8, 8, 8, 8, 8, 8, 8, 3.5],
    'Pore Radius CV(%)': [30, 30, 30, 30, 30, 30, 30, 30],
    'Porosity Mean': [0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.01, 0.0001],
    'Porosity CV(%)': [30, 30, 30, 30, 30, 30, 30, 30],
    'Path Length Mean (um)': [100, 100, 100, 100, 100, 100, 100, 100],
    'Path Length CV(%)': [30, 30, 30, 30, 30, 30, 30, 30],
    'Pore Potential Mean (mV)': [-30, -30, -30, -30, -30, -30, -30, -30],
    'Pore Potential CV(%)': [30, 30, 30, 30, 30, 30, 30, 30]
}

# ========================
# Mucus Layer Parameters
# ========================
MUCUS_LAYER_PARAMS = {
    'Region': ['Stomach', 'Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV', 'Colon'],
    'Total Thickness Mean (um)': [180, 123, 16, 16, 16, 16, 16, 16, 830],
    'Total Thickness CV(%)': [30, 30, 30, 30, 30, 30, 30, 30, 30],
    'Firmly Adherent Thickness Mean (um)': [80, 29, 15, 15, 15, 15, 15, 15, 116],
    'Firmly Adherent Thickness CV(%)': [30, 30, 30, 30, 30, 30, 30, 30, 30],
    'Loosely Adherent Thickness Mean (um)': [100, 94, 1, 1, 1, 1, 1, 1, 714],
    'Loosely Adherent Thickness CV(%)': [30, 30, 30, 30, 30, 30, 30, 30, 30],
    'Pore Size Mean (nm)': [100, 100, 100, 100, 100, 100, 100, 100, 100],
    'Pore Size CV(%)': [30, 30, 30, 30, 30, 30, 30, 30, 30],
    'Water Content Mean (%)': [95, 95, 95, 95, 95, 95, 95, 95, 95],
    'Water Content CV(%)': [30, 30, 30, 30, 30, 30, 30, 30, 30]
}

# ========================
# GI Fluid and Solid Parameters
# ========================
GI_FLUID_SOLID_PARAMS = {
    'Region': ['Stomach', 'Duodenum', 'Jejunum I', 'Jejunum II', 'Ileum I', 'Ileum II', 'Ileum III', 'Ileum IV', 'Colon'],
    'Basal Fluid Volume Fasted Mean (ml)': [35, 25, 18, 18, 14, 14, 14, 14, 11],
    'Basal Fluid Volume Fasted CV(%)': [38, 38, 38, 38, 38, 38, 38, 38, 38],
    'Basal Fluid Volume Fed Mean (ml)': [686, 25, 18, 18, 14, 14, 14, 14, 11],
    'Basal Fluid Volume Fed CV(%)': [16, 38, 38, 38, 38, 38, 38, 38, 38],
    'Basal Solid Mass Fasted Mean (g)': [0, 0, 0, 0, 0, 0, 0, 0, 0],
    'Basal Solid Mass Fasted CV(%)': [0, 0, 0, 0, 0, 0, 0, 0, 0],
    'Basal Solid Mass Fed Mean (g)': [0, 0, 0, 0, 0, 0, 0, 0, 0],
    'Basal Solid Mass Fed CV(%)': [0, 0, 0, 0, 0, 0, 0, 0, 0],
    'Viscosity Fasted Mean (cP)': [1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01],
    'Viscosity Fasted CV(%)': [30, 30, 30, 30, 30, 30, 30, 30, 30],
    'Viscosity Fed Mean (cP)': [1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01, 1.01],
    'Viscosity Fed CV(%)': [30, 30, 30, 30, 30, 30, 30, 30, 30]
}

def clean_tag(tag):
    """Clean parameter tags for consistent naming in output dataframe"""
    # Replace special characters with underscores or appropriate text
    tag = re.sub(r'[^\w\s]', '_', tag)
    # Replace spaces with underscores
    tag = re.sub(r'\s+', '_', tag)
    # Remove duplicate underscores
    tag = re.sub(r'_+', '_', tag)
    # Remove trailing underscores
    tag = tag.strip('_')
    # Convert to lowercase for consistency
    return tag.lower()

class GITransitModel:
    """
    A class to model GI transit times and related parameters.
    """
    
    def __init__(self):
        """Initialize the GI transit model with default parameters."""
        self.transit_params = GI_TRANSIT_PARAMS
        self.physiology_params = GI_PHYSIOLOGY_PARAMS
        self.mrt_params = GI_MRT_PARAMS
        self.meal_event_fluid_params = MEAL_EVENT_FLUID_PARAMS
        self.intestine_anatomy_params = INTESTINE_ANATOMY_PARAMS
        self.immc_cycle_params = IMMC_CYCLE_PARAMS
        self.newe_model_params = NEWE_MODEL_PARAMS
        self.enzyme_protein_abundance_params = ENZYME_PROTEIN_ABUNDANCE_PARAMS
        self.cyp_genotype_data = CYP_GENOTYPE_DATA
        self.distribution_across_intestinal_segments = DISTRIBUTION_ACROSS_INTESTINAL_SEGMENTS
        self.physicochemical_params = PHYSICOCHEMICAL_PARAMS
        self.gi_ph_params = GI_PH_PARAMS
        self.gi_buffer_concentration_params = GI_BUFFER_CONCENTRATION_PARAMS
        self.pka_params = PKA_PARAMS
        self.diffusion_coefficient_params = DIFFUSION_COEFFICIENT_PARAMS
        self.gi_velocity_params = GI_VELOCITY_PARAMS
        self.ion_concentration_params = ION_CONCENTRATION_PARAMS
        self.gi_bile_salt_params = GI_BILE_SALT_PARAMS
        self.villi_params = VILLI_PARAMS
        self.plicae_circulares_params = PLICAE_CIRCULARES_PARAMS
        self.colon_crypts_params = COLON_CRYPTS_PARAMS
        self.paracellular_params = PARACELLULAR_PARAMS
        self.mucus_layer_params = MUCUS_LAYER_PARAMS
        self.gi_fluid_solid_params = GI_FLUID_SOLID_PARAMS
        
    def sample_lognormal(self, mean, cv_percent, size=1):
        """
        Sample from a lognormal distribution given mean and CV%.
        """
        if mean == 0:
            return np.zeros(size)
        cv = cv_percent / 100.0
        variance = (cv * mean) ** 2
        mu = np.log(mean ** 2 / np.sqrt(variance + mean ** 2))
        sigma = np.sqrt(np.log(1 + variance / mean ** 2))
        return np.random.lognormal(mu, sigma, size)
    
    def sample_weibull(self, alpha, beta, size=1):
        """
        Sample from a Weibull distribution with shape parameter alpha and scale parameter beta.
        
        Args:
            alpha: Shape parameter
            beta: Scale parameter
            size: Number of samples to generate
            
        Returns:
            Sampled value(s) from the Weibull distribution
        """
        return beta * np.random.weibull(alpha, size)
    
    def sample_transit_time(self, region, fed_state, size=1):
        """
        Sample transit time for a specific GI region and fed state.
        
        Args:
            region: GI region ('stomach', 'small_intestine', or 'colon')
            fed_state: 'fasted' or 'fed'
            size: Number of samples to generate
            
        Returns:
            Sampled transit time(s) in hours
        """
        params = self.transit_params[region][fed_state]
        distribution = params['distribution']
        
        if distribution == 'lognormal':
            return self.sample_lognormal(params['mean_h'], params['cv_percent'], size)
        elif distribution == 'weibull':
            return self.sample_weibull(params['alpha'], params['beta'], size)
        else:
            raise ValueError(f"Unsupported distribution type: {distribution}")
    
    def sample_total_transit_time(self, fed_state, size=1):
        """
        Sample total GI transit time (sum of stomach, small intestine, and colon).
        
        Args:
            fed_state: 'fasted' or 'fed'
            size: Number of samples to generate
            
        Returns:
            Sampled total transit time(s) in hours
        """
        stomach_tt = self.sample_transit_time('stomach', fed_state, size)
        si_tt = self.sample_transit_time('small_intestine', fed_state, size)
        colon_tt = self.sample_transit_time('colon', fed_state, size)
        
        return stomach_tt + si_tt + colon_tt
    
    def sample_mrt(self, region, fed_state, size=1):
        """
        Sample mean residence time for a specific GI region and fed state.
        
        Args:
            region: GI region (e.g., 'stomach_mrt', 'small_intestine_mrt')
            fed_state: 'fasted' or 'fed'
            size: Number of samples to generate
            
        Returns:
            Sampled MRT(s) in hours
        """
        params = self.mrt_params[region][fed_state]
        return self.sample_lognormal(params['mean'], params['cv_percent'], size)
    
    def generate_gi_parameters(self, n_subjects=1):
        """
        Generate a complete set of GI parameters for n_subjects.
        
        Args:
            n_subjects: Number of subjects to generate parameters for
            
        Returns:
            DataFrame containing all GI parameters for each subject
        """
        # Initialize an empty DataFrame to store all parameters
        all_params = pd.DataFrame()
        
        # Add subject IDs
        all_params['subject_id'] = range(1, n_subjects + 1)
        
        # Generate transit time parameters
        for region in self.transit_params:
            for fed_state in ['fasted', 'fed']:
                column_name = f"gi_transit_{region}_{fed_state}_h"
                all_params[column_name] = self.sample_transit_time(region, fed_state, n_subjects)
        
        # Generate total transit times
        for fed_state in ['fasted', 'fed']:
            column_name = f"gi_transit_total_{fed_state}_h"
            all_params[column_name] = self.sample_total_transit_time(fed_state, n_subjects)
        
        # Generate MRT parameters
        for region in self.mrt_params:
            for fed_state in ['fasted', 'fed']:
                column_name = f"gi_mrt_{region}_{fed_state}_h"
                all_params[column_name] = self.sample_mrt(region, fed_state, n_subjects)
        
        # Generate meal event fluid parameters
        for param, value in self.meal_event_fluid_params.items():
            if isinstance(value, dict) and 'mean' in value and 'cv_percent' in value:
                column_name = f"gi_meal_event_{param}"
                all_params[column_name] = self.sample_lognormal(value['mean'], value['cv_percent'], n_subjects)
            else:
                column_name = f"gi_meal_event_{param}"
                all_params[column_name] = [value] * n_subjects
        
        # Generate IMMC cycle parameters
        column_name = "gi_immc_cycle_time_h"
        all_params[column_name] = self.sample_lognormal(
            self.immc_cycle_params['cycle_time_h']['mean'],
            self.immc_cycle_params['cycle_time_h']['cv_percent'],
            n_subjects
        )
        
        # Generate NEWE model parameters
        column_name = "gi_enterocyte_lifespan_h"
        all_params[column_name] = self.sample_lognormal(
            self.newe_model_params['enterocyte_lifespan_h']['mean'],
            self.newe_model_params['enterocyte_lifespan_h']['cv_percent'],
            n_subjects
        )
        
        column_name = "gi_num_enterocyte_groups"
        all_params[column_name] = [self.newe_model_params['num_enterocyte_groups']] * n_subjects
        
        return all_params
    
    def export_parameters_to_csv(self, output_file='gi_parameters.csv', n_subjects=100):
        """
        Export generated GI parameters to a CSV file.
        
        Args:
            output_file: Path to the output CSV file
            n_subjects: Number of subjects to generate parameters for
        """
        params_df = self.generate_gi_parameters(n_subjects)
        params_df.to_csv(output_file, index=False)
        print(f"Parameters exported to {output_file}")
    
    def plot_transit_time_distribution(self, region='total', fed_state='fasted', n_samples=1000):
        """
        Plot the distribution of transit times for a specific region and fed state.
        
        Args:
            region: GI region ('stomach', 'small_intestine', 'colon', or 'total')
            fed_state: 'fasted' or 'fed'
            n_samples: Number of samples to generate for the plot
        """
        if region == 'total':
            samples = self.sample_total_transit_time(fed_state, n_samples)
            title = f"Total GI Transit Time Distribution ({fed_state})"
        else:
            samples = self.sample_transit_time(region, fed_state, n_samples)
            title = f"{region.capitalize()} Transit Time Distribution ({fed_state})"
        
        plt.figure(figsize=(10, 6))
        plt.hist(samples, bins=30, alpha=0.7, color='skyblue', edgecolor='black')
        plt.axvline(np.mean(samples), color='red', linestyle='dashed', linewidth=2, label=f'Mean: {np.mean(samples):.2f} h')
        plt.axvline(np.median(samples), color='green', linestyle='dashed', linewidth=2, label=f'Median: {np.median(samples):.2f} h')
        plt.title(title)
        plt.xlabel('Transit Time (hours)')
        plt.ylabel('Frequency')
        plt.legend()
        plt.grid(True, alpha=0.3)
        plt.tight_layout()
        plt.show()

def sample_normal(mean, cv, n):
    if cv == 0 or cv is None:
        return np.full(n, mean)
    std = abs(mean) * cv / 100
    return np.random.normal(loc=mean, scale=std, size=n)

def generate_gi_parameters_from_df(pop_df):
    """
    全量输出GI模块所有主要参数，所有标签拼接进参数名，只输出有实际数值意义的列。
    有mean和cv的参数，自动为每个个体采样。不输出CV相关字段。
    """
    import numpy as np
    import pandas as pd
    import re
    def clean_tag(s):
        return re.sub(r'[^a-zA-Z0-9]', '', str(s).replace(' ', '_'))
    n = len(pop_df)
    columns = {}
    columns['id'] = pop_df['id'].values
    np.random.seed(42)
    gi_model = GITransitModel()
    # 1. 转运时间/滞留时间
    columns['gi_stomach_transit_fasted_h'] = gi_model.sample_transit_time('stomach', 'fasted', n)
    columns['gi_stomach_transit_fed_h'] = gi_model.sample_transit_time('stomach', 'fed', n)
    columns['gi_small_intestine_transit_fasted_h'] = gi_model.sample_transit_time('small_intestine', 'fasted', n)
    columns['gi_small_intestine_transit_fed_h'] = gi_model.sample_transit_time('small_intestine', 'fed', n)
    columns['gi_colon_transit_fasted_h'] = gi_model.sample_transit_time('colon', 'fasted', n)
    columns['gi_colon_transit_fed_h'] = gi_model.sample_transit_time('colon', 'fed', n)
    columns['gi_transit_total_fasted_h'] = (
        columns['gi_stomach_transit_fasted_h'] +
        columns['gi_small_intestine_transit_fasted_h'] +
        columns['gi_colon_transit_fasted_h']
    )
    columns['gi_transit_total_fed_h'] = (
        columns['gi_stomach_transit_fed_h'] +
        columns['gi_small_intestine_transit_fed_h'] +
        columns['gi_colon_transit_fed_h']
    )
    # 2. MRT参数
    for region in gi_model.mrt_params:
        for fed_state in ['fasted', 'fed']:
            col = f'gi_mrt_{region}_{fed_state}_h'
            columns[col] = gi_model.sample_mrt(region, fed_state, n)
    # 3. Meal Event Fluid参数
    for param, value in gi_model.meal_event_fluid_params.items():
        if isinstance(value, dict) and 'mean' in value and 'cv_percent' in value:
            columns[f'gi_meal_event_{clean_tag(param)}'] = sample_normal(value['mean'], value['cv_percent'], n)
        else:
            columns[f'gi_meal_event_{clean_tag(param)}'] = [value] * n
    # 4. IMMC/NEWE参数
    columns['gi_immc_cycle_time_h'] = sample_normal(
        gi_model.immc_cycle_params['cycle_time_h']['mean'],
        gi_model.immc_cycle_params['cycle_time_h']['cv_percent'], n)
    columns['gi_enterocyte_lifespan_h'] = sample_normal(
        gi_model.newe_model_params['enterocyte_lifespan_h']['mean'],
        gi_model.newe_model_params['enterocyte_lifespan_h']['cv_percent'], n)
    columns['gi_num_enterocyte_groups'] = [gi_model.newe_model_params['num_enterocyte_groups']] * n
    # 5. PH参数
    for key, values in GI_PH_PARAMS.items():
        if key == 'Segment' or 'CV' in key:
            continue
        cv_key = key + ' CV (%)'
        cv_values = GI_PH_PARAMS.get(cv_key, None)
        for i, val in enumerate(values):
            region = GI_PH_PARAMS['Segment'][i]
            if cv_values is not None:
                cv = cv_values[i]
                arr = sample_normal(val, cv, n)
            else:
                arr = [val] * n
            columns[f'gi_ph_{clean_tag(key)}_{clean_tag(region)}'] = arr
    # 6. 缓冲液参数
    for key, values in GI_BUFFER_CONCENTRATION_PARAMS.items():
        if key == 'Segment' or 'CV' in key:
            continue
        for i, val in enumerate(values):
            region = GI_BUFFER_CONCENTRATION_PARAMS['Segment'][i]
            # 查找CV
            cv = None
            if key.startswith('Fasted'):
                cv_list = GI_BUFFER_CONCENTRATION_PARAMS.get('CV Fasted (%)', None)
                if cv_list is not None:
                    cv = cv_list[i]
            elif key.startswith('Fed'):
                cv_list = GI_BUFFER_CONCENTRATION_PARAMS.get('CV Fed (%)', None)
                if cv_list is not None:
                    cv = cv_list[i]
            if cv is not None:
                arr = sample_normal(val, cv, n)
            else:
                arr = [val] * n
            columns[f'gi_buffer_{clean_tag(key)}_{clean_tag(region)}'] = arr
    # 7. 离子浓度参数
    for i, d in enumerate(ION_CONCENTRATION_PARAMS):
        ion = d.get('Ion', f'Ion{i}')
        metric = d.get('Metric', f'Metric{i}')
        ion_clean = clean_tag(ion)
        metric_clean = clean_tag(metric)
        for k, v in d.items():
            if k in ['Ion', 'Metric'] or 'CV' in k:
                continue
            organ_clean = clean_tag(k)
            cv = None
            # 查找同级的CV
            cv_key = None
            if 'Stomach' in k:
                cv_key = 'CV Stomach (%)'
            elif 'Small Intestine' in k:
                cv_key = 'CV Small Intestine (%)'
            elif 'Colon' in k:
                cv_key = 'CV Colon (%)'
            if cv_key and cv_key in d:
                cv = d[cv_key]
            if cv is not None:
                arr = sample_normal(v, cv, n)
            else:
                arr = [v] * n
            columns[f'gi_ion_{ion_clean}_{metric_clean}_{organ_clean}'] = arr
    # 8. 胆盐参数
    for key, values in GI_BILE_SALT_PARAMS.items():
        if key == 'Segment' or 'CV' in key:
            continue
        for i, val in enumerate(values):
            region = GI_BILE_SALT_PARAMS['Segment'][i]
            # 查找CV
            cv = None
            if key.startswith('[Bile] Fasted'):
                cv_list = GI_BILE_SALT_PARAMS.get('CV [Bile] Fasted (%)', None)
                if cv_list is not None:
                    cv = cv_list[i]
            elif key.startswith('[Bile] Fed'):
                cv_list = GI_BILE_SALT_PARAMS.get('CV [Bile] Fed (%)', None)
                if cv_list is not None:
                    cv = cv_list[i]
            if cv is not None:
                arr = sample_normal(val, cv, n)
            else:
                arr = [val] * n
            columns[f'gi_bile_{clean_tag(key)}_{clean_tag(region)}'] = arr
    # 9. 绒毛/皱襞/隐窝/旁细胞参数
    for param_set, param_dict in [
        (VILLI_PARAMS, 'gi_villi'),
        (PLICAE_CIRCULARES_PARAMS, 'gi_plicae'),
        (COLON_CRYPTS_PARAMS, 'gi_coloncrypt'),
        (PARACELLULAR_PARAMS, 'gi_paracellular'),
    ]:
        for key, values in param_set.items():
            if key == 'Region' or 'CV' in key:
                continue
            # 查找CV列
            if f'{key} CV(%)' in param_set:
                cv_list = param_set[f'{key} CV(%)']
            else:
                cv_list = None
            for i, val in enumerate(values):
                region = param_set['Region'][i]
                cv = None
                if cv_list is not None:
                    cv = cv_list[i]
                if cv is not None:
                    arr = sample_normal(val, cv, n)
                else:
                    arr = [val] * n
                columns[f'{param_dict}_{clean_tag(key)}_{clean_tag(region)}'] = arr
    # 10. 黏液层参数
    for key, values in MUCUS_LAYER_PARAMS.items():
        if key == 'Region' or 'CV' in key:
            continue
        if f'{key} CV(%)' in MUCUS_LAYER_PARAMS:
            cv_list = MUCUS_LAYER_PARAMS[f'{key} CV(%)']
        else:
            cv_list = None
        for i, val in enumerate(values):
            region = MUCUS_LAYER_PARAMS['Region'][i]
            cv = None
            if cv_list is not None:
                cv = cv_list[i]
            if cv is not None:
                arr = sample_normal(val, cv, n)
            else:
                arr = [val] * n
            columns[f'gi_mucus_{clean_tag(key)}_{clean_tag(region)}'] = arr
    # 11. 流体/固体/粘度参数
    for key, values in GI_FLUID_SOLID_PARAMS.items():
        if key == 'Region' or 'CV' in key:
            continue
        if f'{key} CV(%)' in GI_FLUID_SOLID_PARAMS:
            cv_list = GI_FLUID_SOLID_PARAMS[f'{key} CV(%)']
        else:
            cv_list = None
        for i, val in enumerate(values):
            region = GI_FLUID_SOLID_PARAMS['Region'][i]
            cv = None
            if cv_list is not None:
                cv = cv_list[i]
            if cv is not None:
                arr = sample_normal(val, cv, n)
            else:
                arr = [val] * n
            columns[f'gi_fluidsolid_{clean_tag(key)}_{clean_tag(region)}'] = arr
    # 12. 其它参数（如物理化学、分布等）可按需补充
    gi_df = pd.DataFrame(columns)
    return gi_df

def export_gi_params_to_csv(output_dir='gi_params'):
    """
    Export all GI parameter sets to CSV files.
    
    Args:
        output_dir: Directory to save the CSV files
    """
    # Create the output directory if it doesn't exist
    os.makedirs(output_dir, exist_ok=True)
    
    # Create a GI transit model
    gi_model = GITransitModel()
    
    # Export transit parameters
    transit_df = pd.DataFrame()
    for region in gi_model.transit_params:
        for fed_state in ['fasted', 'fed']:
            params = gi_model.transit_params[region][fed_state]
            row = {
                'Region': region,
                'Fed State': fed_state,
                'Distribution': params.get('distribution', ''),
                'Mean (h)': params.get('mean_h', ''),
                'CV (%)': params.get('cv_percent', ''),
                'Alpha': params.get('alpha', ''),
                'Beta': params.get('beta', '')
            }
            transit_df = pd.concat([transit_df, pd.DataFrame([row])], ignore_index=True)
    transit_df.to_csv(f"{output_dir}/transit_parameters.csv", index=False)
    
    # Export MRT parameters
    mrt_df = pd.DataFrame()
    for region in gi_model.mrt_params:
        for fed_state in ['fasted', 'fed']:
            params = gi_model.mrt_params[region][fed_state]
            row = {
                'Region': region,
                'Fed State': fed_state,
                'Mean (h)': params['mean'],
                'CV (%)': params['cv_percent']
            }
            mrt_df = pd.concat([mrt_df, pd.DataFrame([row])], ignore_index=True)
    mrt_df.to_csv(f"{output_dir}/mrt_parameters.csv", index=False)
    
    # Export meal event fluid parameters
    meal_df = pd.DataFrame(columns=['Parameter', 'Value', 'CV (%)'])
    for param, value in gi_model.meal_event_fluid_params.items():
        if isinstance(value, dict) and 'mean' in value and 'cv_percent' in value:
            row = {
                'Parameter': param,
                'Value': value['mean'],
                'CV (%)': value['cv_percent']
            }
        else:
            row = {
                'Parameter': param,
                'Value': value,
                'CV (%)': 'N/A'
            }
        meal_df = pd.concat([meal_df, pd.DataFrame([row])], ignore_index=True)
    meal_df.to_csv(f"{output_dir}/meal_event_parameters.csv", index=False)
    
    # Export intestine anatomy parameters
    anatomy_df = pd.DataFrame()
    for param, value in gi_model.intestine_anatomy_params.items():
        if isinstance(value, dict):
            for subparam, subvalue in value.items():
                row = {
                    'Parameter': param,
                    'Subparameter': subparam,
                    'Value': subvalue
                }
                anatomy_df = pd.concat([anatomy_df, pd.DataFrame([row])], ignore_index=True)
        else:
            row = {
                'Parameter': param,
                'Subparameter': 'N/A',
                'Value': value
            }
            anatomy_df = pd.concat([anatomy_df, pd.DataFrame([row])], ignore_index=True)
    anatomy_df.to_csv(f"{output_dir}/intestine_anatomy_parameters.csv", index=False)
    
    # Export enzyme and protein abundance parameters
    enzyme_df = pd.DataFrame(gi_model.enzyme_protein_abundance_params)
    enzyme_df.to_csv(f"{output_dir}/enzyme_protein_abundance_parameters.csv", index=False)
    
    # Export CYP genotype data
    cyp_df = pd.DataFrame()
    for cyp, data in gi_model.cyp_genotype_data.items():
        for item in data:
            item['CYP'] = cyp
            cyp_df = pd.concat([cyp_df, pd.DataFrame([item])], ignore_index=True)
    cyp_df.to_csv(f"{output_dir}/cyp_genotype_data.csv", index=False)
    
    # Export distribution across intestinal segments
    dist_df = pd.DataFrame(gi_model.distribution_across_intestinal_segments)
    dist_df.to_csv(f"{output_dir}/distribution_across_intestinal_segments.csv", index=False)
    
    # Export physicochemical parameters
    phys_df = pd.DataFrame(columns=['Parameter', 'Value'])
    for param, value in gi_model.physicochemical_params.items():
        row = {
            'Parameter': param,
            'Value': value
        }
        phys_df = pd.concat([phys_df, pd.DataFrame([row])], ignore_index=True)
    phys_df.to_csv(f"{output_dir}/physicochemical_parameters.csv", index=False)
    
    # Export GI pH parameters
    ph_df = pd.DataFrame(gi_model.gi_ph_params)
    ph_df.to_csv(f"{output_dir}/gi_ph_parameters.csv", index=False)
    
    # Export GI buffer concentration parameters
    buffer_df = pd.DataFrame(gi_model.gi_buffer_concentration_params)
    buffer_df.to_csv(f"{output_dir}/gi_buffer_concentration_parameters.csv", index=False)
    
    # Export pKa parameters
    pka_df = pd.DataFrame(gi_model.pka_params)
    pka_df.to_csv(f"{output_dir}/pka_parameters.csv", index=False)
    
    # Export diffusion coefficient parameters
    diff_df = pd.DataFrame(gi_model.diffusion_coefficient_params)
    diff_df.to_csv(f"{output_dir}/diffusion_coefficient_parameters.csv", index=False)
    
    # Export GI velocity parameters
    vel_df = pd.DataFrame(gi_model.gi_velocity_params)
    vel_df.to_csv(f"{output_dir}/gi_velocity_parameters.csv", index=False)
    
    # Export ion concentration parameters
    ion_df = pd.DataFrame(gi_model.ion_concentration_params)
    ion_df.to_csv(f"{output_dir}/ion_concentration_parameters.csv", index=False)
    
    # Export GI bile salt parameters
    bile_df = pd.DataFrame(gi_model.gi_bile_salt_params)
    bile_df.to_csv(f"{output_dir}/gi_bile_salt_parameters.csv", index=False)
    
    # Export villi parameters
    villi_df = pd.DataFrame(gi_model.villi_params)
    villi_df.to_csv(f"{output_dir}/villi_parameters.csv", index=False)
    
    # Export plicae circulares parameters
    plicae_df = pd.DataFrame(gi_model.plicae_circulares_params)
    plicae_df.to_csv(f"{output_dir}/plicae_circulares_parameters.csv", index=False)
    
    # Export colon crypts parameters
    crypts_df = pd.DataFrame(gi_model.colon_crypts_params)
    crypts_df.to_csv(f"{output_dir}/colon_crypts_parameters.csv", index=False)
    
    # Export paracellular parameters
    para_df = pd.DataFrame(gi_model.paracellular_params)
    para_df.to_csv(f"{output_dir}/paracellular_parameters.csv", index=False)
    
    # Export mucus layer parameters
    mucus_df = pd.DataFrame(gi_model.mucus_layer_params)
    mucus_df.to_csv(f"{output_dir}/mucus_layer_parameters.csv", index=False)
    
    # Export GI fluid and solid parameters
    fluid_df = pd.DataFrame(gi_model.gi_fluid_solid_params)
    fluid_df.to_csv(f"{output_dir}/gi_fluid_solid_parameters.csv", index=False)
    
    print(f"All parameter sets exported to {output_dir}/")

if __name__ == "__main__":
    # Create a GI transit model
    gi_model = GITransitModel()
    
    # Generate parameters for 5 subjects
    params_df = gi_model.generate_gi_parameters(5)
    print(params_df.head())
    
    # Export parameters to CSV
    gi_model.export_parameters_to_csv(n_subjects=100)
    
    # Plot transit time distributions
    gi_model.plot_transit_time_distribution(region='stomach', fed_state='fasted')
    gi_model.plot_transit_time_distribution(region='stomach', fed_state='fed')
    gi_model.plot_transit_time_distribution(region='total', fed_state='fasted')
    
    # Export all parameter sets to CSV files
    export_gi_params_to_csv()
    
    # Example of using generate_gi_parameters_from_df
    # Create a sample DataFrame with kidney parameters
    kidney_df = pd.DataFrame({
        'subject_id': range(1, 6),
        'kidney_weight_g': [300, 320, 290, 310, 305],
        'kidney_blood_flow_ml_min': [1200, 1250, 1180, 1220, 1210]
    })
    
    # Add GI parameters to the kidney parameters
    combined_df = generate_gi_parameters_from_df(kidney_df)
    print(combined_df.head())

def clean_gi_parameter_name(name):
    """清理GI参数名称，移除特殊字符"""
    return re.sub(r'[^a-zA-Z0-9]', '', str(name))


def clean_gi_transporter_name(name):
    """清理GI转运体名称，保留括号但移除其他特殊字符"""
    # 保留括号、字母、数字，移除其他特殊字符
    return re.sub(r'[^a-zA-Z0-9()]', '', str(name))


def sample_lognormal_gi(mean, cv, size=1):
    """从对数正态分布采样（GI模块专用）"""
    if mean <= 0:
        return np.zeros(size)
    sigma_log = np.sqrt(np.log(1 + (cv/100)**2))
    mu_log = np.log(mean) - 0.5 * sigma_log**2
    return np.exp(np.random.normal(loc=mu_log, scale=sigma_log, size=size))


def generate_gi_cyp_genotypes_and_phenotypes(pop_df, random_seed=42):
    """
    生成GI CYP酶基因型和表型数据
    
    参数:
    pop_df: 包含id的人口统计学DataFrame
    random_seed: 随机种子
    
    返回:
    包含GI CYP基因型和表型的DataFrame
    """
    np.random.seed(random_seed)
    n_subjects = len(pop_df)
    results = {}
    results['id'] = pop_df['id'].values
    
    # 为每个GI CYP酶生成基因型和表型
    for cyp_name in GI_CYP_FREQUENCIES.keys():
        frequencies = GI_CYP_FREQUENCIES[cyp_name]
        abundances = GI_CYP_ABUNDANCES[cyp_name]
        
        # 生成基因型
        phenotypes = list(frequencies.keys())
        phenotype_probs = list(frequencies.values())
        
        # 确保概率和为1
        total_prob = sum(phenotype_probs)
        if total_prob > 0:
            phenotype_probs = [p/total_prob for p in phenotype_probs]
        else:
            phenotype_probs = [1.0] + [0.0] * (len(phenotypes) - 1)
        
        # 为每个人分配基因型
        genotypes = np.random.choice(phenotypes, size=n_subjects, p=phenotype_probs)
        
        # 生成对应的表型数据
        abundances_values = []
        turnover_values = []
        
        for i, genotype in enumerate(genotypes):
            # 获取该基因型的丰度参数
            abundance_params = abundances[genotype]
            mean_abundance = abundance_params['mean']
            cv_abundance = abundance_params['cv']
            
            # 生成丰度值
            if mean_abundance > 0:
                abundance = sample_lognormal_gi(mean_abundance, cv_abundance, 1)[0]
            else:
                abundance = 0.0
            
            abundances_values.append(abundance)
            
            # 生成周转时间（所有人使用相同的周转参数）
            if i == 0:  # 只在第一次计算周转时间
                turnover_mean = abundances['turnover_mean']
                turnover_cv = abundances['turnover_cv']
                turnover = sample_lognormal_gi(turnover_mean, turnover_cv, 1)[0]
                turnover_values = [turnover] * n_subjects
        
        # 存储结果
        clean_cyp = clean_gi_parameter_name(cyp_name)
        results[f'GI_{clean_cyp}_genotype'] = genotypes
        results[f'GI_{clean_cyp}_abundance_pmol_mg'] = abundances_values
        results[f'GI_{clean_cyp}_turnover_1_h'] = turnover_values
    
    return pd.DataFrame(results)


def generate_gi_transporter_genotypes_and_phenotypes(pop_df, random_seed=42):
    """
    生成GI转运体基因型和表型数据
    
    参数:
    pop_df: 包含id的人口统计学DataFrame
    random_seed: 随机种子
    
    返回:
    包含GI转运体基因型和表型的DataFrame
    """
    np.random.seed(random_seed)
    n_subjects = len(pop_df)
    results = {}
    results['id'] = pop_df['id'].values
    
    # 为每个GI转运体生成基因型和表型
    for transporter_name in GI_TRANSPORTER_FREQUENCIES.keys():
        frequencies = GI_TRANSPORTER_FREQUENCIES[transporter_name]
        abundances = GI_TRANSPORTER_ABUNDANCES[transporter_name]
        
        # 生成基因型
        phenotypes = list(frequencies.keys())
        phenotype_probs = list(frequencies.values())
        
        # 确保概率和为1
        total_prob = sum(phenotype_probs)
        if total_prob > 0:
            phenotype_probs = [p/total_prob for p in phenotype_probs]
        else:
            phenotype_probs = [1.0] + [0.0] * (len(phenotypes) - 1)
        
        # 为每个人分配基因型
        genotypes = np.random.choice(phenotypes, size=n_subjects, p=phenotype_probs)
        
        # 生成对应的表型数据
        abundances_values = []
        turnover_values = []
        
        for i, genotype in enumerate(genotypes):
            # 获取该基因型的丰度参数
            abundance_params = abundances[genotype]
            mean_abundance = abundance_params['mean']
            cv_abundance = abundance_params['cv']
            
            # 生成丰度值
            if mean_abundance > 0:
                abundance = sample_lognormal_gi(mean_abundance, cv_abundance, 1)[0]
            else:
                abundance = 0.0
            
            abundances_values.append(abundance)
            
            # 生成周转时间（所有人使用相同的周转参数）
            if i == 0:  # 只在第一次计算周转时间
                turnover_mean = abundances['turnover_mean']
                turnover_cv = abundances['turnover_cv']
                turnover = sample_lognormal_gi(turnover_mean, turnover_cv, 1)[0]
                turnover_values = [turnover] * n_subjects
        
        # 存储结果
        clean_transporter = clean_gi_transporter_name(transporter_name)
        results[f'GI_{clean_transporter}_genotype'] = genotypes
        results[f'GI_{clean_transporter}_abundance_pmol_mg'] = abundances_values
        results[f'GI_{clean_transporter}_turnover_1_h'] = turnover_values
    
    return pd.DataFrame(results)


def generate_gi_enzymes_transporters_from_df(pop_df, random_seed=42):
    """
    生成GI酶和转运体参数的主函数
    
    参数:
    pop_df: 包含id的人口统计学DataFrame
    random_seed: 随机种子
    
    返回:
    包含GI酶和转运体参数的DataFrame
    """
    # 生成GI CYP酶数据
    gi_cyp_df = generate_gi_cyp_genotypes_and_phenotypes(pop_df, random_seed)
    
    # 生成GI转运体数据
    gi_transporter_df = generate_gi_transporter_genotypes_and_phenotypes(pop_df, random_seed)
    
    # 合并GI CYP酶和转运体数据
    result_df = pd.merge(gi_cyp_df, gi_transporter_df, on='id', how='left')
    
    return result_df
